﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WorldBankBBS.Input;
using WorldBankBBS.Logic;
using WorldBankBBS.Pathing;
using WorldBankBBS.Translators;

namespace WorldBankBBS.Menus
{
    public class MenuProcessor
    {
        private event TextInputHandler TextInput;

        private class UnknownContext : IContextItem
        {
            public string Context { get; set; }
        }

        public void ProcessMenu(IMenuProvider provider, Session session)
        {
            InputHandler inputHandler = new InputHandler();

            var translator = session.Encoding.GetTranslator(session);

            var buffer = new byte[1024];
            var l = 0;

            var done = false;

            while (!done)
            {
                provider.Refresh(session);
                var context = session["MenuContext"] as IContextItem ?? new UnknownContext() { Context = string.Empty };
                var messages = session["MenuLookups"] as IDictionary<string, Guid> ?? new Dictionary<string, Guid>();
                var threads = session["MenuThreadLookups"] as IDictionary<string, Guid> ?? new Dictionary<string, Guid>();
                var subboards = session["MenuSubboardLookups"] as IDictionary<string, Guid> ?? new Dictionary<string, Guid>();
                

                l = translator.StringToBytes(buffer, provider.Prompt);
                session.Connection.SendData(buffer, 0, l, l);

                TextInput -= inputHandler.OnTextInput;
                TextInput += inputHandler.OnTextInput;

                var choice = TextInput(session, translator, session.Connection, 15, false).ToLower();

                TextInput -= inputHandler.OnTextInput;

                MenuItem mi = null;

                if (choice == "?" || choice == "help")
                {
                    l = translator.StringToBytes(buffer, provider.GenericHelpText);
                    session.Connection.SendData(buffer, 0, l, 1);
                }
                else if (choice == "" && (mi = provider.MenuItems.FirstOrDefault(x => x.Abbreviation == "")) != null)
                {
                    // Default action
                    new PathRouter(session).PerformRoute(mi.GetResourcePath());
                }
                else
                {
                    foreach (var item in provider.MenuItems)
                    {
                        var a = false;

                        if (choice != "" && (a = choice.StartsWith(item.Abbreviation.ToLower())) || choice.StartsWith(item.Full.ToLower()))
                        {
                            if (string.IsNullOrWhiteSpace(item.ResourcePattern))
                            {
                                done = true;
                                break;
                            }

                            if (item.TakesParameters)
                            {
                                var parameter = a
                                    ? choice.Substring(item.Abbreviation.Length)
                                    : choice.Substring(item.Full.Length);

                                if (parameter.Length > 0 && messages.ContainsKey(parameter))
                                {
                                    var lookupItem = messages[parameter];
                                    new PathRouter(session).PerformRoute(item.GetResourcePath(lookupItem.ToString()));
                                    break;
                                }
                            }

                            if (item.TakesThreadParameter)
                            {
                                var parameter = a
                                    ? choice.Substring(item.Abbreviation.Length)
                                    : choice.Substring(item.Full.Length);

                                if (parameter.Length > 0 && threads.ContainsKey(parameter))
                                {
                                    var lookupItem = threads[parameter];
                                    new PathRouter(session).PerformRoute(item.GetResourcePath(lookupItem.ToString()));
                                    break;
                                }
                            }

                            if (item.TakesSubboardParameter)
                            {
                                var parameter = a
                                    ? choice.Substring(item.Abbreviation.Length)
                                    : choice.Substring(item.Full.Length);

                                if (parameter.Length > 0 && subboards.ContainsKey(parameter))
                                {
                                    var lookupItem = subboards[parameter];
                                    new PathRouter(session).PerformRoute(item.GetResourcePath(lookupItem.ToString()));
                                    break;
                                }
                            }

                            if (item.UseCurrentContext)
                            {
                                //var lookupItem = lookups[context.Context];
                                new PathRouter(session).PerformRoute(item.GetResourcePath(context.Context));
                                break;
                            }

                            if (!item.UseCurrentContext && !item.TakesParameters && (choice == item.Abbreviation.ToLower() || choice == item.Full.ToLower()))
                            {
                                new PathRouter(session).PerformRoute(item.GetResourcePath());
                                break;
                            }

                            break;
                        }

                        if (item.Abbreviation == "#" && messages.ContainsKey(choice))
                        {
                            var lookupItem = messages[choice];
                            new PathRouter(session).PerformRoute(item.GetResourcePath(lookupItem.ToString()));
                            break;
                        }
                    }
                }

                Thread.Sleep(100);
            }
        }
    }
}
